using System;
using System.Web.Caching;
using System.Configuration;
using System.Runtime.InteropServices;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using Microsoft.SharePoint.Administration;
using System.Data;
using System.Data.SqlClient;
using System.Security.Principal;
using System.Net.Mail;
using EAT.Common;

namespace EAT.SiteCollectionApproval
{
    [Guid("CF5B715C-2FD9-4c97-970F-4F4265B20497")]
    public class SiteCollectionApproval : System.Web.UI.WebControls.WebParts.WebPart
    {
        Label TextLabel;
        SqlManager SqlM;
        WebPartTable WPT;

        //
        // INDEX provides indices for the columns of the SiteTable.
        //
        enum INDEX
        {
            URL = 0,
            REQUESTER,
            NUMBER,
            JUSTIFICATION,
            ACTION,
            Max
        }

        string[] ColumnNames;


        public SiteCollectionApproval()
        {
            this.ExportMode = WebPartExportMode.All;
        }

        //
        // OnLoad
        // Arguments:
        //      e - EventArgs that may contain Postback data
        // Description:
        //      Initialize internal members and respond to Postback.
        //
        protected override void OnLoad(EventArgs e)
        {
            SPWeb web = SPControl.GetContextWeb(Context);
            string mailMsg = null;
            string resultString = null;
            string[] Params;
            string eventArg;
            string action = null;
            string requester = null;
            string url = null;
            string number = null;
            string tag = null;

            WPT = new WebPartTable("SCA");
            TextLabel = new Label();
            SqlM = new SqlManager();

            ColumnNames = new string[(int)INDEX.Max];

            ColumnNames[(int)INDEX.URL]           = Resources.requestedURLColumnHeaderText;
            ColumnNames[(int)INDEX.REQUESTER]     = Resources.requesterColumnHeaderText;
            ColumnNames[(int)INDEX.NUMBER]        = Resources.requestNumberColumnHeaderText;
            ColumnNames[(int)INDEX.JUSTIFICATION] = Resources.justificationColumnHeaderText;
            ColumnNames[(int)INDEX.ACTION]        = Resources.actionColumnHeaderText;

            if (Page.IsPostBack)
            {
                eventArg = Page.Request["__EVENTARGUMENT"];

                if (eventArg.Length > 0)
                {
                    Params = eventArg.Split(",".ToCharArray());

                    //
                    // Postback must have at least 2 parameters.  The first is a tag
                    // indicating the intended target of the postback.  The second is 
                    // an action for the application to perform.
                    //
                    if (Params.Length > 1)
                    {
                        tag = Params[0];
                        action = Params[1];

                        if (WPT.GetTag() == tag)
                        {
                            switch (action)
                            {
                                case "approvesite":
                                    {
                                        if (Params.Length == 5)
                                        {
                                            url = Params[2];
                                            requester = Params[3];
                                            number = Params[4];

                                            if (ApproveOrDeny(
                                                    true,
                                                    url,
                                                    number,
                                                    ref resultString
                                                    ))
                                            {
                                                mailMsg = string.Format(Resources.successfulCreationEmailBodyText, HttpUtility.UrlPathEncode(resultString));

                                                TextLabel.Text = string.Format(Resources.successfulCreationLabelText, resultString);
                                            }
                                        }
                                        break;
                                    }
                                case "denysite":
                                    {
                                        if (Params.Length == 5)
                                        {
                                            url = Params[2];
                                            requester = Params[3];
                                            number = Params[4];

                                            if (ApproveOrDeny(
                                                    false,
                                                    url,
                                                    number,
                                                    ref resultString
                                                    ))
                                            {
                                                mailMsg = string.Format(Resources.deniedRequestEmailBodyText, url, Context.User.Identity.Name);

                                                TextLabel.Text = string.Format(Resources.deniedRequestLabelText, url);
                                            }
                                        }
                                        break;
                                    }
                                case "sort":
                                    {
                                        if (Params.Length == 4)
                                        {
                                            //
                                            // The column and direction are read from the URL.
                                            //
                                            WPT.SetSortColumn(Params[2]);
                                            WPT.SetSortOrder(Params[3]);
                                        }
                                        break;
                                    }
                                default:
                                    break;
                            }
                        }
                        if (mailMsg != null)
                        {
                            SPUser CurrentUser = web.CurrentUser;
                            SPUser RequesterUser = web.AllUsers[requester];
                            if (RequesterUser.Email != null && RequesterUser.Email != "")
                            {
                                MailMessage Msg = new MailMessage();
                                SmtpClient Client = new SmtpClient();

                                Msg.To.Add(new MailAddress(RequesterUser.Email));

                                Msg.Subject = Resources.siteProvisioningEmailSubjectText;
                                Msg.From = new MailAddress(
                                                   SqlM.GetEntry("Config", "eMailSource")
                                                   );
                                Msg.Body = mailMsg;
                                Client.Send(Msg);
                            }
                        }
                    }
                }
            }
            else
            {
                base.OnLoad(e);
            }

            ConstructPendingSiteTable();
        }

        //
        // ConstructPendingSiteTable
        // Arguments - none.
        // Description:
        //      Build the SiteTable.  Key off of the URL.  Add columns for owner, 
        //      description, title, requester, and workflow status.  Query SQL and 
        //      Sharepoint to populate the table.
        //
        protected void ConstructPendingSiteTable()
        {
            DataColumn[] key;
            DataColumn dc;

            key = new DataColumn[1];
            key[0] = new DataColumn(
                             ColumnNames[(int)INDEX.URL], 
                             typeof(String)
                             );
            WPT.GetTable().Columns.Add(key[0]);
            WPT.GetTable().PrimaryKey = key;

            dc = new DataColumn(
                         ColumnNames[(int)INDEX.REQUESTER],
                         typeof(String)
                         );

            WPT.GetTable().Columns.Add(dc);

            dc = new DataColumn(
                         ColumnNames[(int)INDEX.NUMBER],
                         typeof(String)
                         );

            WPT.GetTable().Columns.Add(dc);

            dc = new DataColumn(
                         ColumnNames[(int)INDEX.JUSTIFICATION],
                         typeof(String)
                         );

            WPT.GetTable().Columns.Add(dc);
            GetPendingSites(WPT.GetTable());
        }

        //
        // Render
        // Arguments:
        //      writer - HtmlTextWriter that outputs the controls.
        // Description:
        //      Render draws the webpart.
        //
        protected override void Render(HtmlTextWriter writer)
        {
            if (!IsApprover())
            {
                writer.Write(Resources.noPermissionsText);
                return;
            }

            writer.Write("<table border=\"0\" width=\"100%\" class=\"ms-authoringcontrols\">");
            writer.Write(@"<tr class=""grid-header"" align=""left"" style=""color:White;background-color:#5D7B9D;font-weight:bold;"">");
            writer.Write(@"<th><a style=""color:White;"">" + ColumnNames[(int)INDEX.ACTION] + "</th>");
            writer.Write(@"<th><a style=""color:White;"">" + WPT.SortLink(ColumnNames[(int)INDEX.URL]) + "</th>");
            writer.Write(@"<th><a style=""color:White;"">" + WPT.SortLink(ColumnNames[(int)INDEX.REQUESTER]) + "</th>");
            writer.Write(@"<th><a style=""color:White;"">" + WPT.SortLink(ColumnNames[(int)INDEX.JUSTIFICATION]) + "</th>");
            writer.Write("</tr>");
            
            string Url;
            string Requester;
            string RequestNum;
            string Justification;

            foreach (DataRow dr in WPT.GetSortedRows(null))
            {
                Url = dr[(int)INDEX.URL].ToString().Trim();
                Requester = dr[(int)INDEX.REQUESTER].ToString().Trim();
                RequestNum = dr[(int)INDEX.NUMBER].ToString().Trim();
                Justification = dr[(int)INDEX.JUSTIFICATION].ToString().Trim();
                
                writer.Write("<tr>");

                //
                // The first entry is a hyperlink to approve the site.
                //
                string tag = @"<td><a href=""javascript:__doPostBack('__Page','";
                tag += WPT.GetTag() + ",approvesite," + Url + "," + Requester.Replace("\\", "\\\\") + "," + RequestNum;
                tag += @"')"" style=""color:#0000FF;"">" + Resources.approveVerbText + "</a> ";
                writer.Write(tag);

                // 
                // The second hyperlink is the deny tag.
                //
                tag = @"<a href=""javascript:__doPostBack('__Page','";
                tag += WPT.GetTag() + ",denysite," + Url + "," + Requester.Replace("\\", "\\\\") + "," + RequestNum;
                tag += @"')"" style=""color:#0000FF;"">" + Resources.denyVerbText + "</a></td>";
                writer.Write(tag);

                writer.Write("<td>" + Url + "</td>");
                writer.Write("<td>" + Requester + "</td>");
                writer.Write("<td>" + Justification + "</td>");
                writer.Write("</tr>");
            }

            foreach (Control c in this.Controls)
            {
                writer.Write("<tr><td colspan=4>");
                writer.Write(c.ID + " ");
                c.RenderControl(writer);
                writer.Write("</td></tr>");
            }

            writer.Write("</table>");
        }


        protected override void CreateChildControls()
        {
            this.Controls.Add(TextLabel);
        }

        //
        // ApproveOrDeny
        // Arguments:
        //      fApprove - boolean indicating if the site is approved or denied.
        //      siteURL - string URL for the site.
        //      requestNum - internal tracking number for SQL
        //      Result - string reference describing the result of the operation
        // Description:
        //      This routine approves or denies sites to deal with postback.  It updates
        //      SQL with relevant information regarding the action.
        //
        public bool ApproveOrDeny(
                        bool fApprove,
                        string siteURL,
                        string requestNum,
                        ref string Result
                        )
        {
            int nRequestNum = int.Parse(requestNum);

            if (fApprove)
            {
                SPHelper SPH = new SPHelper();
                string Title = null;
                string Description = null;
                string Requester = null;
                string Template = null;
                SPUser RequesterUser = null;

                Title = SqlM.GetEntry(
                            "SiteProvision",
                            "SiteURL",
                            siteURL,
                            "SiteTitle"
                            );

                Description = SqlM.GetEntry(
                                       "SiteProvision",
                                       "SiteURL",
                                       siteURL,
                                       "SiteDescription"
                                       );
                Requester = SqlM.GetEntry(
                                 "SiteProvision",
                                 "SiteURL",
                                 siteURL,
                                 "Requester"
                                 );
                Template = SqlM.GetEntry(
                                    "SiteProvision",
                                    "SiteURL",
                                    siteURL,
                                    "Template"
                                    );

                RequesterUser = SPControl.GetContextWeb(System.Web.HttpContext.Current).AllUsers[Requester];

                if (SPH.CreateCollaborationSite(
                            siteURL,
                            Title,
                            Description,
                            RequesterUser,
                            Template
                            ))
                {
                    SqlM.SetEntry(
                             "SiteProvision",
                             "Approver",
                             Context.User.Identity.Name,
                             "RequestNum",
                             requestNum
                             );
                    SqlM.SetEntry(
                             "SiteProvision",
                             "Status",
                             "Approved",
                             "RequestNum",
                             requestNum
                             );
                    SqlM.SetEntry(
                             "SiteProvision",
                             "ApproveTimeStamp",
                             DateTime.Now.ToShortDateString(),
                             "RequestNum",
                             requestNum
                             );

                    SPWeb web = SPControl.GetContextWeb(System.Web.HttpContext.Current);
                    Result = web.Url.ToString() + "/" + siteURL;
                }
                else
                {
                    Result = string.Format(Resources.provisioningFailedLabelText, siteURL);
                    return false;
                }
            }
            else
            {
                SqlM.SetEntry(
                         "SiteProvision",
                         "Approver",
                         Context.User.Identity.Name,
                         "RequestNum",
                         requestNum
                         );
                SqlM.SetEntry(
                         "SiteProvision",
                         "Status",
                         "Denied",
                         "RequestNum",
                         requestNum
                         );
                SqlM.SetEntry(
                         "SiteProvision",
                         "ApproveTimeStamp",
                         DateTime.Now.ToShortDateString(),
                         "RequestNum",
                         requestNum
                         );
            }
            return true;
        }

        //
        // GetPendingSites
        // Arguments:
        //      dt - DataTable to populate with information.
        // Description:
        //      This reads the pending sites from SQL and enters information into
        //      the passed DataTable.
        //
        public void GetPendingSites(
                        DataTable dt
                        )
        {
            string Value = "";
            DataRow dr;

            try
            {
                SqlDataReader reader = SqlM.GetReader(
                                                "SiteProvision",
                                                "Status",
                                                "Pending"
                                                );

                while (reader.Read())
                {
                    dr = dt.NewRow();

                    dr[(int)INDEX.URL] = reader["SiteURL"].ToString();
                    
                    try
                    {
                        dr[(int)INDEX.REQUESTER] = reader["Requester"].ToString(); 
                    }
                    catch
                    {
                        dr[(int)INDEX.REQUESTER] = Resources.noRequesterText;
                    }
                    
                    dr[(int)INDEX.NUMBER] = reader["RequestNum"].ToString();
                    dr[(int)INDEX.JUSTIFICATION] = reader["Justification"].ToString();

                    dt.Rows.Add(dr);
                }
                reader.Close();
            }
            catch (Exception e)
            {
                Value = e.Message;
            }
        }
        
        //
        // IsApprover
        // Arguments: none
        // Description:
        //      This routine determines if the current user is a member
        //      of the group listed under SCWorkflowApprovers.
        //
        bool IsApprover()
        {
            return WPT.IsUserInConfigGroup(
                       SPControl.GetContextWeb(Context).CurrentUser,
                       "SCWorkflowApprovers"
                       );
        }
    }
}
